const writeUUID =   "00009822-AE15-BC10-5202-856A95FCD178"; //write UUID
const notifyUUID =  "00009822-AE15-BC10-5203-856A95FCD178"; //notify UUID
const filterServiceUUID = "00009822-AE15-BC10-5201-856A95FCD178"; //Service UUID

var _discoveryStarted = false;
var deviceId = ''; //用于区分设备的 id
var _serviceId = '';
var status = false; //当前状态
var isnotExist = true;
var ble_rec_callback;
var bt_state_change_callback;
var PhoneBluetoothAdapterStateChangeCallback;


function get_ble_dev_id(){
  return deviceId;
}

function get_ble_dev_service_id(){
  return _serviceId;
}

/**
 * 断开蓝牙连接
 */
function closeBLEConnection() {

  //停止搜索
  stopBluetoothDevicesDiscovery();
  console.log("Disconnect BT Dev", deviceId);

  if (deviceId) {
    wx.closeBLEConnection({
      deviceId: deviceId,
      success: function (res) {
        console.log("closeBLEConnection。success", res);
      },
      fail: function (res) {
        console.log("closeBLEConnection。fail", res);
      },
      complete: function () {
        status = false;
      }
    })

    //关闭蓝牙模块
    wx.closeBluetoothAdapter({
      success: function (res) {
        console.log("closeBluetoothAdapter res:", res);
      },
      fail: function (error) {
        console.log("closeBluetoothAdapter error:", error);
      }
    })
  }
  _discoveryStarted = false;
  isnotExist = true;
  deviceId = '';
}
// 初始化蓝牙模块
function ble_start(filtUUID,filtDevName,dat_rec_cb,bt_state_chang_cb,phoneBtStateChangeCB) {
  //断开连接
  console.log('bt init start>>>>>>>>:');
  ble_rec_callback = dat_rec_cb;
  bt_state_change_callback = bt_state_chang_cb;
  PhoneBluetoothAdapterStateChangeCallback = phoneBtStateChangeCB;
  closeBLEConnection();
  wx.openBluetoothAdapter({
    success: (res) => {
      console.log('openBluetoothAdapter:', res)
      // 监听寻找新设备事件
      onBluetoothDeviceFound(filtDevName);
      //开始搜寻附近的蓝牙外围设备
      startBluetoothDevicesDiscovery(filtUUID);
    },
    fail: (res) => {
      console.log('bt start error-code:'+res.errCode)
      if (res.errCode == 10001) {
        //监听蓝牙适配器状态变化事件
        wx.onBluetoothAdapterStateChange(function (res) {
          console.log('bt state change:  ', res)
          if (res.available) {
            console.log('bt avaliabl:-->')
            onBluetoothDeviceFound(filtDevName);
            //开始搜寻附近的蓝牙外围设备
            startBluetoothDevicesDiscovery(filtUUID);
          }
        })
      }
      asddErrorCallback(res.errCode, "");
    }
  })
}

//开始查找BLE设备
function startBluetoothDevicesDiscovery(filterUUID) {
  console.log("start dev discovery:" + _discoveryStarted+'uuid:'+filterUUID);
  if (_discoveryStarted) {
    return;
  }
  _discoveryStarted = true
  wx.startBluetoothDevicesDiscovery({
    services: filterUUID, //只搜索广播包有对应 uuid 的主服务的蓝牙设备。
    allowDuplicatesKey: false,
    success: (res) => {},
    fail(res) {
      asddErrorCallback(res.errCode, "");
      console.log('startBluetoothDevicesDiscovery fail', res);
    }
  })
}

//停止搜寻附近的蓝牙外围设备。
function stopBluetoothDevicesDiscovery() {
  wx.stopBluetoothDevicesDiscovery()
}
/** 连接蓝牙设备*/
function createBLEConnection(device_ID) {
  wx.createBLEConnection({
    deviceId: device_ID,
    success: (res) => {
      wx.showToast({
        title: '设备连接成功',
        duration: 2000
      })
      getBLEDeviceServices(device_ID)
    },
    fail: (res) => {
      console.log('create-BLE-Connection fail', res);
      asddErrorCallback(res.errCode, "");
    }
  })
  //停止搜索
  stopBluetoothDevicesDiscovery();
}

/**发现BLE设备服务 */
function getBLEDeviceServices(deviceId) {
  //监听低功耗蓝牙连接状态的改变事件
  wx.onBLEConnectionStateChange(function (res) {
    console.log("onBLEConnectionStateChange:", res);
    // 该方法回调中可以用于处理连接意外断开等异常情况
    console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
    if (res.connected == false) {
      console.log("连接异常", deviceId);
      deviceId = '';

    }
    bt_state_change_callback(res);
  });
  //获取蓝牙所有service
  wx.getBLEDeviceServices({
    deviceId: deviceId,
    success: (res) => {
      // console.log("获取蓝牙设备所有服务(service)", res);
      for (let i = 0; i < res.services.length; i++) {
        let tmpUuid = res.services[i].uuid;
        console.log('tmpUuid:', tmpUuid);
        console.log('primary:',res.services[i].isPrimary,'filtUUID:'+tmpUuid.indexOf(filterServiceUUID));
        if ((res.services[i].isPrimary) && (tmpUuid.indexOf(filterServiceUUID) != -1)) {
          //获取蓝牙特征值
          getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
          return;
        }
      }
    },
    fail: (res) => {
      console.log('ge-tBLE-Services fail', res);
      asddErrorCallback(res.errCode, "");
    }
  })
}

/** 获取蓝牙特征值*/
function getBLEDeviceCharacteristics(deviceId, serviceId) {
  console.log("device：" + deviceId + 'services：' + serviceId);
  wx.getBLEDeviceCharacteristics({
    deviceId: deviceId,
    serviceId: serviceId,
    success: (res) => {
      // console.log('蓝牙设备特征值信息:', res);
      console.log('getBLEDeviceCharacteristics success', res.characteristics)
      _serviceId = serviceId
      for (let i = 0; i < res.characteristics.length; i++) {
        let item = res.characteristics[i]
        var itemUUID = item.uuid.toUpperCase(); //转大写
        // if (item.properties.read && itemUUID == readUUID) { //read操作
        if (item.properties.read) { //read操作
          console.log("Read uuid:" + item.uuid);
          wx.readBLECharacteristicValue({
            deviceId: deviceId,
            serviceId: serviceId,
            characteristicId: item.uuid,
          })
        }
        if (item.properties.write && itemUUID == writeUUID) { //write操作
          console.log("Write uuid:" + item.uuid);
        }
        if ((item.properties.notify || item.properties.indicate) && notifyUUID == itemUUID) { //notify操作，注意调用监听特征值变化
          console.log('Notify uuid:' + item.uuid);
          // 必须先启用 wx.notifyBLECharacteristicValueChange 才能监听到设备 onBLECharacteristicValueChange 事件
          wx.notifyBLECharacteristicValueChange({
            deviceId: deviceId,
            serviceId: serviceId,
            characteristicId: item.uuid,
            state: true,
            success(res) {
              console.log('notification-res', res);
              status = true;
            },
            fail(res) {
              console.log('notifyBLECharacteristicValueChange fali', res);
            }
          })
        }
      }
    },
    fail: (res) => {
      console.log('getBLEDeviceCharacteristics fail', res)
      asddErrorCallback(res.errCode, "");
    }
  })

  // 操作之前先监听，保证第一时间获取数据
  wx.onBLECharacteristicValueChange(function (res) {
    // console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
    //var resData = ab2hex(res.value); //转16进制
    var resData = ab2str(res.value); //转string
    // console.log("notify get datas:"+ resData);
    /*@TODO To handle cmd */
    // ble_notify_data_handle(res.value);
    ble_rec_callback(resData);
  })
}

function ble_writeData(dev_id,hex) {
  if (!status) {
    return;
  }
  if (!dev_id) {
    asddWriteErrors('w');
    return;
  }
  // console.log("ble send dat：" + hex)
  setTimeout(() => {
    //类型转换
    // var str=hex.split('');
    // console.log(str);
    // var enDataBuf = new Uint8Array();
     var enDataBuf = toUint8Arr(hex);
    // var enDataBuf = str2ab(hex);
   // var enDataBuf = hex;
     var buffer1 = enDataBuf.buffer;
    console.log(enDataBuf);
    wx.writeBLECharacteristicValue({
      deviceId: dev_id,
      serviceId: _serviceId,
      characteristicId: writeUUID,
      value: buffer1,
      success: (res) => {
       // wx.hideLoading();
        // console.log("写数据返回结果", res.errMsg);
      },
      fail(res) {
        console.log("写数据失败..", res);
        asddErrorCallback(res.errCode, "");
      }
    })
  }, 100)
}

//对搜索到的BLE设备进行筛选
function onBluetoothDeviceFound(filterName) {
  wx.onBluetoothDeviceFound((res) => {
    console.log('adv data result:', res);
    res.devices.forEach(device => {
      if (!device.name && !device.localName) {
        return
      }
      // 转换后, 得出相关数据
      var hexStr = ab2hex(device.advertisData);
      console.log(device.localName + "advertisData---->" + device.advertisData);
      // //通过设备名称进行匹配
      
      if ((Object.keys(filterName).length > 0) ? device.localName == filterName : 1 && isnotExist) {
        isnotExist = false;
        deviceId = device.deviceId;
        console.log('DeviceId:' + deviceId);
        //停止搜寻附近的蓝牙外围设备
        stopBluetoothDevicesDiscovery();
        //连接设备
        createBLEConnection(deviceId);
      }
    })
  })
}

/**
 * 去掉 冒号
 */
function clearSymbol(str) {
  str = str.replace(/:/g, ""); //取消字符串中出现的所有冒号
  return str;
}
/**
 * rrayBuffer转16进度字符串
 */
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}
function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint8Array(buf));
}
function str2ab(str) {
  var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
  var bufView = new Uint8Array(buf);
  for (var i=0, strLen=str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}
function toUint8Arr(str) {
  const buffer = [];
  for (let i of str) {
      const _code = i.charCodeAt(0);
      if (_code < 0x80) {
          buffer.push(_code);
      } else if (_code < 0x800) {
          buffer.push(0xc0 + (_code >> 6));
          buffer.push(0x80 + (_code & 0x3f));
      } else if (_code < 0x10000) {
          buffer.push(0xe0 + (_code >> 12));
          buffer.push(0x80 + (_code >> 6 & 0x3f));
          buffer.push(0x80 + (_code & 0x3f));
      }
  }
  return Uint8Array.from(buffer);
}

function phoneBtStateChangeONinit() {
  // wx.onBluetoothAdapterStateChange(function (res) {
  //   console.log('bt state change:  ', res)
  //   PhoneBluetoothAdapterStateChangeCallback(res);
  // })
}

module.exports = {
  ble_start,
  closeBLEConnection,
  ble_writeData,
  getBLEDeviceCharacteristics,
  stopBluetoothDevicesDiscovery,
  startBluetoothDevicesDiscovery,
  ab2hex,
  clearSymbol,
  asddErrorCallback,
  onBluetoothDeviceFound,
  get_ble_dev_id,
  get_ble_dev_service_id,
  phoneBtStateChangeONinit,
}

//function bluetoothStatus(errorType) {
  function asddErrorCallback(errorType) {
    switch (errorType) {
      case 10001:
        wx.showModal({
          title: '提示',
          content: '请检查手机蓝牙是否打开',
          showCancel: false
        })
        break;
      case 10002:
        wx.showToast({
          title: '没有找到指定设备',
          icon: 'none'
        })
        break;
      case 10003:
        wx.showToast({
          title: '连接失败',
          icon: 'none'
        })
        closeBLEConnection();
        break;
      case 10004:
        wx.showToast({
          title: '没有找到指定服务',
          icon: 'none'
        })
        closeBLEConnection();
        break;
      case 10005:
        wx.showToast({
          title: '没有找到指定特征值',
          icon: 'none'
        })
        closeBLEConnection();
        break;
      case 10007:
      case 10008:
      case 10013:
        wx.showToast({
          title: '设备启动失败，请重试',
          icon: 'none'
        })
        break;
      case 10009:
        wx.showModal({
          title: '提示',
          content: '当前系统版本过低，请更新版本体验',
          showCancel: false
        })
        break;
      case 10012:
        wx.showToast({
          title: '连接超时',
          icon: 'none'
        })
        break;
    }
  }

